/*
 * @Description: 
 * @Author: xubin
 * @Date: 2022-02-25 11:14:18
 * @LastEditors: xubin
 * @LastEditTime: 2022-03-02 11:17:23
 */
import __DB__       from '../db/index.js';
import __canvas__   from '../canvas/index.js';
import __tool__     from '../tool/index.js';

class formateHawkEyeClass {
    constructor(){
        this.one = [];
        this.many = [];
        this.space_x = 5;
        this.space_y = 5;
        this.node = {
            w:10,
            h:5
        }
        this.size = {
            w:200,
            h:150
        }
    }

    // 初始化
    init(res){
        let elCanvasMain = document.getElementById('eye');
        if(!elCanvasMain)return;

        this.one = __tool__.deepCopy(res);
        this.many = [this.one[0]];
        this.formartData_many();

        this.matchH();// 解析节点 计算出各节点的各种高度
        this.matchW();// 解析节点 计算出各节点的各种宽度
        
        let oldElCanvas = document.getElementById('canvas');
        if(oldElCanvas)oldElCanvas.remove();
        
        let elCanvas = document.createElement('canvas');
        elCanvas.setAttribute('id','canvas');
        elCanvas.setAttribute('width',this.size.w);
        elCanvas.setAttribute('height',this.size.h);
        
        elCanvasMain.appendChild(elCanvas);
        this.clearCanvas();// 清除画布
        this.canvas_root();// 绘制根节点可获得根节点坐标
        this.canvas_nodes();// 绘制剩余节点
    }

    // 清除画布
    clearCanvas()  {  
        var cxt=document.getElementById("canvas").getContext("2d");
        cxt.clearRect(0,0,this.size.w,this.size.h);  
    }  

    // 绘制根节点可获得根节点坐标
    canvas_root(){
        let elCanvas = document.getElementById('canvas');
        let ctx = elCanvas.getContext("2d");
        let maxMain = {
            w:this.size.w,
            h:this.size.h
        }

        let x1 = maxMain.w/2 - this.node.w/2,
            y1 = maxMain.h/2 - this.node.h/2;

        this.many[0].init.poi = {
            x:x1,
            y:y1,
        };

        let rr = __tool__.autoPoi({
            w:this.node.w,
            h:this.node.h,
            x:x1,
            y:y1
        })

        this.many[0].init.point = rr.point;

        this.matchPoi();// 解析节点 计算出需要的坐标

        this.one.forEach((el,i)=>{
            if(i === 0){
                ctx.fillStyle="#207CFC";
                ctx.fillRect(x1,y1,this.node.w,this.node.h);
            }
            
        });        
    }

    // 绘制剩余节点
    canvas_nodes(){
        let elCanvas = document.getElementById('canvas');
        let ctx = elCanvas.getContext("2d");

        recursion(this.many)
        function recursion(items){
            items.forEach(el=>{
                if(el.root){
                    if(el.children_l.length > 0)recursion(el.children_l);
                    if(el.children_r.length > 0)recursion(el.children_r);
                }
                else{
                    let x = el.init.poi.x,
                        y = el.init.poi.y,
                        w = el.init.size.w,
                        h = el.init.size.h;
                    
                    let color = '#059af3';
                    if(el.nodeType === 'compute'){
                        color = '#fb685c';
                    }
                    else if(el.nodeType === 'resource'){
                        color = '#f9bb1f';
                    }
                    else if(el.nodeType === 'general'){
                        color = '#207cfc';
                    }

                    ctx.fillStyle=color;
                    ctx.fillRect(x,y,w,h);
                    
                    if(el.children.length > 0)recursion(el.children);
                }
            })
        }
    }

    // 自动格式化节点数据
    nodeModel(item){
        let children    = [],
            children_l  = [],
            children_r  = [];

        if(item.root){
            children_l = item.node.childrenRoot.flip;
            children_r = item.node.childrenRoot.unFlip;
        }
        else{
            children = item.node.children;
        }

        let obj = {
            id          : item.id||null,
            label       : item.label||null,
            pid         : item.pid||null,
            root        : item.root||false,
            flip        : item.flip||false,
            type        : 'tree',
            show        : true,
            nodeType    : item.nodeType||'rule',
            children    : children,
            children_l  : children_l,
            children_r  : children_r,
            init        : {
                poi     : item.init?item.init.poi:{x:0,y:0},                             // 坐标
                point   : {a:[],b:[],c:[],d:[],ab:[],bc:[],cd:[],ad:[],mid:[]},          // 周围八个点
                size    : {w:this.node.w,h:this.node.h},                                 // 尺寸
                max     : {top:0,h:0,w:0,ch:0},                                          // h是包括节点自己的最大高，ch是除了自己所有子节点的最大高
                maxRoot : {
                    l : {top:0,h:0,w:0,ch:0},                                            // h是包括节点自己的最大高，ch是除了自己所有子节点的最大高
                    r : {top:0,h:0,w:0,ch:0},                                            // h是包括节点自己的最大高，ch是除了自己所有子节点的最大高
                },
            }
        }

        return obj;
    }

    // 格式化一维节点数据
    formartData_one(){
        let oldOne = __tool__.deepCopy(this.one);
        let newOne = oldOne.map(item=>{
            item = this.nodeModel(item);// 自动格式化节点数据
            return item;
        });

        this.one = newOne;
    }

    // 格式化多维节点数据
    formartData_many(){
        let _this = this;
        recursion(this.many);
        function recursion(items){
            items.forEach((el,i)=>{
                el = _this.nodeModel(el);// 自动格式化节点数据
                items[i] = el;
                if(el.root){
                    if(el.children_l.length > 0){
                        recursion.call(this,el.children_l);
                    }
                    if(el.children_r.length > 0){
                        recursion.call(this,el.children_r);
                    }
                }
                else{
                    recursion.call(this,el.children);
                }
            });
        }
    }

    // 解析节点 计算出各节点的各种高度
    matchH(){
        recursion.call(this,this.many,null);
        function recursion(items,parent){
            let max = {
                l:{w:0,h:0},
                r:{w:0,h:0},
            };

            items.forEach((el,i)=>{
                if(el.root){
                    let rb = null,h = 0,w = 0,maxh = 0,maxw = 0;
                    // let root = __DB__.get('root');
                    if(el.children_l.length > 0){
                        let rb =recursion.call(this,el.children_l,null);

                        // 最大高
                        maxh = rb.l.h;
                        el.init.maxRoot.l.ch = maxh;
                        h = el.init.size.h;
                        maxh = h<maxh?maxh:h;
                        el.init.maxRoot.l.h = maxh;

                        let mid = el.init.point.mid;
                        
                        // el.init.maxRoot.l.top = mid[1] - maxh/2;
                    }

                    if(el.children_r.length > 0){
                        let rb = recursion.call(this,el.children_r,null);

                        // 最大高
                        maxh = rb.r.h;
                        el.init.maxRoot.r.ch = maxh;
                        h = el.init.size.h;
                        maxh = h<maxh?maxh:h;
                        el.init.maxRoot.r.h = maxh;

                        let mid = el.init.point.mid;
                        // el.init.maxRoot.r.top = mid[1] - maxh/2;

                        
                    }
                }
                else{
                    if(el.flip){
                        fn_left.call(this,el);
                    }
                    else{
                        fn_right.call(this,el);
                    }
                    
                }
            });

            return max;

            function fn_left(item){
                let init = item.init;
                let h = parseFloat(init.size.h.toFixed(2)) + this.space_y;
                // 如果没有同胞就减掉垂直间距
                if(parent&&parent.root&&parent.children_l.length === 1){
                    h = h - this.space_y;
                }
                else if(parent&&parent.children && parent.children.length === 1){
                    h = h - this.space_y;
                }

                if(item.children.length > 0){
                    let w1 = item.children[0].init.size.w + this.space_x;
                    item.children.forEach(el=>{
                        let w = el.init.size.w + this.space_x;
                        w1 = w1>w?w1:w;
                    });

                    max.l.w += w1;

                    let rb = recursion.call(this,item.children,item);
                    let maxh = rb.l.h;
                    init.max.ch = maxh;
                    maxh = h<maxh?maxh:h;
                    init.max.h = maxh;
                    max.l.h += maxh;
                    max.l.w += rb.l.w;
                    return;
                }

                init.max.h = h;
                init.max.ch = h;
                max.l.h += h;
                
            }
            function fn_right(item){
                let init = item.init,
                    children = item.children;
                
                let h = parseFloat(init.size.h.toFixed(2)) + this.space_y;

                // 如果没有同胞就减掉垂直间距
                if(parent&&parent.root&&parent.children_r.length === 1){
                    h = h - this.space_y;
                }
                else if(parent&&parent.children && parent.children.length === 1){
                    h = h - this.space_y;
                }

                if(children.length > 0){
                    let w1 = children[0].init.size.w + this.space_x;
                    children.forEach(el=>{
                        let w = el.init.size.w + this.space_x;
                        w1 = w1>w?w1:w;
                    });
                    max.r.w += w1;

                    let rb = recursion.call(this,children,item);

                    let maxh = rb.r.h;
                    init.max.ch = maxh;

                    maxh = h<maxh?maxh:h;
                    init.max.h = maxh;
                    max.r.h += maxh;
                    return;
                }

                init.max.h      = h;
                init.max.ch     = h;
                max.r.h         += h;
            }
        }
    }

    // 解析节点 计算出各节点的各种宽度
    matchW(){
        let _this = this;
        recursion(this.many);
        function recursion(items) {
            let maxw = 0;
            items.forEach(el=>{
                if(el.root){
                    if(el.children_l.length > 0){
                        recursion(el.children_l);

                        let w1 = el.children_l[0].init.max.w;
                        el.children_l.forEach(item=>{
                            let w = item.init.max.w;
                            w1 = w1>w?w1:w;
                        });

                        el.init.maxRoot.l.w = w1;
                    }
                    if(el.children_r.length > 0){
                        recursion(el.children_r);

                        let w1 = el.children_r[0].init.max.w;
                        el.children_r.forEach(item=>{
                            let w = item.init.max.w;
                            w1 = w1>w?w1:w;
                        });

                        el.init.maxRoot.r.w = w1;
                    }
                }
                else{
                    el.show = true;
                    fn_child(el);
                }
            })

            return maxw;

            function fn_child(item) {
                let node = item;
                let w = node.init.size.w + _this.space_x;
                w = w/__canvas__.scale;
                node.init.max.w = w;
                if(node.children.length > 0){
                    let rb = recursion(node.children);
                    let w1 = node.children[0].init.max.w;
                    node.children.forEach(el=>{
                        let w = el.init.max.w;
                        w1 = w1>w?w1:w;
                    });
                    maxw = w1 + w;
                    node.init.max.w = rb + w;
                }
                else{
                    maxw = maxw>w?maxw:w;
                }
            }
        }
    }

    // 解析节点 计算出需要的坐标
    matchPoi(items){
        let _this = this;

        recursion(this.many);
        return items;
        function recursion(items,parent){
            let myChild = [];
            items.forEach((el,i)=>{
                if(el.root){
                    if(el.children_l.length > 0){
                        myChild.push({children:el.children_l,parent:el,root:true});
                    }

                    if(el.children_r.length > 0){
                        myChild.push({children:el.children_r,parent:el,root:true});
                    }
                    return;
                }

                myChild.push({
                    children:el.children,
                    parent:el,
                    flip:el.flip,
                });

                if(el.flip){
                    fn_left(el,i);
                }
                else{
                    fn_right(el,i);
                }
            });

            if(myChild.length === 0)return;

            for(let el of myChild){
                recursion(el.children,el.parent);
            }

            function fn_left(item,index) {
                if(!parent)return;
                let init    = item.init;
                let pMid    = parent.init.point.mid;
                let pCh     = parent.root?parent.init.maxRoot.l.ch:parent.init.max.ch;
                let ph      = parent.root?parent.init.maxRoot.l.h:parent.init.max.h;
                let left    = pMid[0] - parent.init.size.w/2 - _this.space_x - init.size.w;
                let maxTop  = pMid[1] - ph/2;
                let top     = null;

                if(index === 0){
                    let oo = init.max.h/2 - init.size.h/2;//如果自己小于后代的高度，减掉除自身外的高度除2来做为本节点的TOP
                    if(ph > pCh){maxTop = pMid[1] - pCh/2;}// 如果自己比后代的高度要高度，改变最大TOP
                    
                    top             = maxTop + oo;
                    init.max.top    = maxTop;
                    init.poi.x      = left;
                    init.poi.y      = top;
                }
                else{
                    top             = items[index-1].init.max.top + items[index-1].init.max.h;
                    init.max.top    = top;
                    top             = top + (init.max.h/2 - init.size.h/2);
                    init.poi.x      = left;
                    init.poi.y      = top;
                }
                
                let itemPoi = __tool__.autoPoi({
                    w:init.size.w,
                    h:init.size.h,
                    x:left,
                    y:top
                });
                init.point = itemPoi.point;
            };

            function fn_right(item,index) {
                
                if(!parent)return;
                let init    = item.init;
                let pMid    = parent.init.point.mid;
                let pCh     = parent.root?parent.init.maxRoot.r.ch:parent.init.max.ch;
                let ph      = parent.root?parent.init.maxRoot.r.h:parent.init.max.h;
                let left    = pMid[0] + parent.init.size.w/2 + _this.space_x;
                let maxTop  = pMid[1] - ph/2;
                let top     = null;

                if(index === 0){
                    let oo = init.max.h/2 - init.size.h/2;//如果自己小于后代的高度，减掉除自身外的高度除2来做为本节点的TOP
                    if(ph > pCh){maxTop = pMid[1] - pCh/2;}// 如果自己比后代的高度要高度，改变最大TOP
                    
                    top             = maxTop + oo;

                    init.max.top    = maxTop;
                    init.poi.x      = left;
                    init.poi.y      = top;
                }
                else{
                    top             = items[index-1].init.max.top + items[index-1].init.max.h;
                    init.max.top    = top;
                    top             = top + (init.max.h/2 - init.size.h/2);

                    init.poi.x      = left;
                    init.poi.y      = top;
                }
                
                let itemPoi = __tool__.autoPoi({
                    w:init.size.w,
                    h:init.size.h,
                    x:left,
                    y:top
                });
                init.point = itemPoi.point;
            };
        }
    }
}

let formateHawkEye = new formateHawkEyeClass();
export default formateHawkEye;